/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 
/**************************************************************************
 ** NUC900 Graphics Engine Programming Reference
 ** - solid fill with foreground color
 ** - solid fill with background color
 ** - solid fill with 8x8 color pattern
 ** - solid fill with 8x8 mono pattern
 **
 ** PC50 Walter Tseng, 2004
 **************************************************************************/

#ifdef ECOS
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "drv_api.h"
#include "diag.h"
#include "wbio.h"
#include "NUC900_GE.h"
#include "NUC900_reg.h"
#else
#include <stdio.h>
#include "NUC900_GE.h"
#include "wbio.h"
#ifdef _NUC900_
#include "NUC900_reg.h"
#else
#include "reg702.h"
#endif
#endif

/*
** No normalization in the implementation. 
** Therefore, the caller must guarantee x2 > x1 and y2 > y1.
** 
**/

///////////////////////////////////////////////////////////////////////////////
//
// Function: solid_fill()
//
// Description:
//   Rectangle solid color fill with foreground color.
//   Source Data Select : foreground color
///////////////////////////////////////////////////////////////////////////////
void solid_fill(int dx, int dy, int width, int height, int color)
{
  UINT32 cmd32, color32;
  UINT32 dest_start, dest_pitch, dest_dimension;
  
  #ifdef DEBUG 
  printf("solid_fill()\n");
  printf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
  printf("color=0x%x\n", color);
  #endif 
 
  color32 = make_color(color);
  
  //printf("color32 is %x\n",color32);
 
  cmd32 = 0xcc430060; 
  outpw(REG_2D_GEC, cmd32);
  outpw(REG_2D_GEFC, color32); // fill with foreground color

  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  dest_start = dy << 16 | dx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dest_dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dest_dimension);

  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  
  
  outpw(REG_2D_GEC, cmd32);
  
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}


///////////////////////////////////////////////////////////////////////////////
//
// Function: solid_fill_back()
//
// Description:
//   Rectangle solid color fill with background color.
//   Source Data Select : background color
///////////////////////////////////////////////////////////////////////////////
void solid_fill_back(int dx, int dy, int width, int height, int color)
{
  UINT32 cmd32, color32;
  UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG  
  printf("solid_fill_back()\n");
  printf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1,dy+height-1);
  printf("color=0x%x\n", color);
#endif 
  
  color32 = make_color(color);
 
  cmd32 = 0xcc430040; 
  outpw(REG_2D_GEC, cmd32);
  outpw(REG_2D_GEBC, color32); // fill with foreground color

  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  dest_start = dy << 16 | dx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dest_dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dest_dimension);

  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  
  
  outpw(REG_2D_GEC, cmd32);
  
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}


///////////////////////////////////////////////////////////////////////////////
//
// Function: color_pattern_fill()
//
// Description:
//   Rectangle fill with 8x8 color pattern.
//   The color pattern data is stored in the offscreen buffer.
//
///////////////////////////////////////////////////////////////////////////////
void color_pattern_fill(int dx, int dy, int width, int height)
{
  UINT32 cmd32;
  UINT32 dest_start, dest_pitch, dest_dimension;
  UINT32 data32, alpha;

#ifdef DEBUG 
  printf("color_pattern_fill()\n");
  printf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
  printf("pattern offset (%d,%d)\n", dx%8, dy%8);
#endif  

  //outpw(REG_2D_GEPLS, (int)GFX_PAT_ADDR);  //smf
  
  cmd32 = 0xf0430000; 
  outpw(REG_2D_GEC, cmd32);

  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  dest_start = dy << 16 | dx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dest_dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dest_dimension);
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }

  // can do transparent?

  // can do alpha-blending? No, it can't
  
  #if 0
  //
  // reset FIFO (test)
  //
  cmd32 = inpw(REG_2D_GEMC);
  outpw(REG_2D_GEMC, cmd32 | 0x40); // FIFO reset
  outpw(REG_2D_GEMC, cmd32);
  #endif
    
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}


///////////////////////////////////////////////////////////////////////////////
//
// Function: mono_pattern_fill()
//
// Description:
//   Rectangle fill with 8x8 mono pattern.
//   The mono pattern is specified by two control registers (8 bytes).
//
///////////////////////////////////////////////////////////////////////////////
void mono_pattern_fill(int dx, int dy, int width, int height, int opt)
{
  UINT32 cmd32;
  UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG 
  printf("mono_pattern_fill()\n");
  printf("(%d,%d)-(%d,%d)\n", dx, dy, dx+width-1, dy+height-1);
#endif     

  cmd32 = 0xf0430010; 
  if (opt==MODE_TRANSPARENT)
  {
    cmd32 |= 0x00006000;
  }
  outpw(REG_2D_GEC, cmd32);

  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  dest_start = dy << 16 | dx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dest_dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dest_dimension);
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }

  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}

///////////////////////////////////////////////////////////////////////////////
//
// Function: color_pattern_rop_fill()
//
// Description:
//   Rectangle fill with 8x8 color pattern.
//   The color pattern data is stored in the offscreen buffer.
//
///////////////////////////////////////////////////////////////////////////////
void color_pattern_rop_fill(int sx, int sy, int width, int height, int rop)
{
  UINT32 cmd32;
  UINT32 dest_start, dest_pitch, dest_dimension;
  
#ifdef DEBUG  
  printf("color_pattern_fill()\n");
  printf("(%d,%d)-(%d,%d)\n", sx, sy, sx+width-1, sy+height-1);
  printf("pattern offset (%d,%d)\n", sx%8, sy%8);
#endif 
 
  //cmd32 = 0xf0430000; 
  cmd32 = 0x00430000 | (rop<<24);
  outpw(REG_2D_GEC, cmd32);

  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  dest_start = sy << 16 | sx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dest_dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dest_dimension);
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }

  // can do transparent?
  
  // can do alpha-blending?
  
  #if 0
  //
  // reset FIFO (test)
  //
  cmd32 = inpw(REG_2D_GEMC);
  outpw(REG_2D_GEMC, cmd32 | 0x40); // FIFO reset
  outpw(REG_2D_GEMC, cmd32);
  #endif
    
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}


///////////////////////////////////////////////////////////////////////////////
//
// Function: mono_pattern_rop_fill()
//
// Description:
//   Rectangle fill with 8x8 mono pattern.
//   The mono pattern is specified by two control registers (8 bytes).
//
///////////////////////////////////////////////////////////////////////////////
void mono_pattern_rop_fill(int sx, int sy, int width, int height, int rop,int opt)
{
  UINT32 cmd32;
  UINT32 dest_start, dest_pitch, dest_dimension;

#ifdef DEBUG  
  printf("mono_pattern_fill()\n");
  printf("(%d,%d)-(%d,%d)\n", sx, sy, sx+width-1, sy+height-1);
#endif   
 
  //cmd32 = 0xf0430010; 
  cmd32 = 0x00430010 | (rop<<24);
  if (opt==MODE_TRANSPARENT)
  {
    cmd32 |= 0x00006000;
  }
  outpw(REG_2D_GEC, cmd32);

  dest_pitch = GFX_WIDTH << 16; // pitch in pixel
  outpw(REG_2D_GESDP, dest_pitch);
  
  dest_start = sy << 16 | sx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dest_dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dest_dimension);
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }

  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}

/*
** NOTE:
** The tile height and width are changed to CR0000 bit 31 to b16.
** The tile height and width are reversed
*/
///////////////////////////////////////////////////////////////////////////////
//
// Function: tile_blt_fill()
//
// Description:
//   TileBLT function. //The source image is in on-screen surface.
//
///////////////////////////////////////////////////////////////////////////////
void tile_blt_fill(int srcx, int srcy, int destx, int desty, int width, int height, int x_count, int y_count)
{
  UINT32 cmd32, pitch, dest_start, src_start, dimension;  
  UINT32 tile_ctl;

#ifdef DEBUG 
  printf("tile_blt_image()\n");
  printf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
  printf("width=%d height=%d\n", width, height);
  printf("%dx%d grids\n", x_count, y_count);
#endif  

  if (x_count > 0) x_count--;
  if (y_count > 0) y_count--;
  
  cmd32 = 0xcc430400; // b10 is the tile control
  
  outpw(REG_2D_GEC, cmd32); 
  
  pitch = GFX_WIDTH << 16 | GFX_WIDTH; // pitch in pixel
  //pitch = GFX_WIDTH << 16 | srcpitch; // pitch in pixel
  outpw(REG_2D_GESDP, pitch);

  src_start = srcy << 16 | srcx;           // redundancy ??
  outpw(REG_2D_GESSXYL, src_start);  // redundancy ??
  
  dest_start = desty << 16 | destx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dimension);  
  
  /*
  outpw(REG_2D_GEXYSORG, GFX_START_ADDR);
  */
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  
 
#ifdef GE_REV6
#ifdef _NUC900_
  tile_ctl = (y_count << 8) | (x_count);
  outpw(REG_2D_TileXY_VHSF, tile_ctl); 
  outpw(REG_2D_GETG, 1); 
#else
  tile_ctl = (y_count << 24) | (x_count << 16);
  tile_ctl |= 1; // GO bit
  outpw(REG_2D_GETG, tile_ctl); 
#endif  
#else   
  tile_ctl = (inpw(REG_2D_GEMC) & 0x0000ffff) | (y_count << 24) | (x_count << 16);
  outpw(REG_2D_GEMC, tile_ctl);
  outpw(REG_2D_GETG, 1); 
#endif
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status  
}


